using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MySqlConnector;
using RFS.BizLogic.utils;
using RFS.Domain.PaiShi.Zuhuo;
using ycx;

namespace RFS.BizLogic.PaiShi.Ports.Adapters
{
    public class ObjectSaver<T>
    {
        private readonly string _connectionString;
        private readonly List<T> _objects;
        private readonly ILog _log;


        public ObjectSaver(string connectionString, IEnumerable<T> os, int objectsPerCnn = 20, ILog log = null)
        {
            var objects = os.ToList();
            var maxc = objects.Count / objectsPerCnn;
            connections = Math.Max(maxc, 1);
            // connections = Math.Min(connections, 10 );

            _log = log;
            _connectionString = connectionString;
            _objects = objects;
        }

        int connections = 5; // Adjust the number of connections

        public async Task SaveObjectsAsync(Action<MySqlConnection, MySqlTransaction, T> saver)
        {
            await Task.Run(async () =>
            {
                var tasks = new List<Task>();

                var objectBatches = _objects.Split(connections).ToList(); // Split objects into batches

                1.TryRun(()=>_log.Info($"已拆成[{connections}/{objectBatches.FirstOrDefault().Count}]") );
                
                foreach (var batch in objectBatches)
                {
                    tasks.Add(SaveObjectBatchAsync(batch, saver));
                }

                await Task.WhenAll(tasks);
                1.TryRun(()=>_log.Info($"已完成[{connections}/{objectBatches.FirstOrDefault().Count}]任务") );

            });
        }


        private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(100, 100);
         
        
        
        private async Task SaveObjectBatchAsync(List<T> batch, Action<MySqlConnection, MySqlTransaction, T> saver)
        {
            try
            {
                await _semaphore.WaitAsync();
        
                using (var connection = GetConnection())
                {
                    await connection.OpenAsync();
                    using (var transaction = connection.BeginTransaction())
                    {
                        try
                        {
                            // Prepare the SQL statement (replace with your actual INSERT statement)
                            foreach (var z in batch)
                            {
                                saver(connection, transaction, z);
                            }
                            transaction.Commit();
                            _log.Info($" 已保存:{batch.Count} 项");
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            _log.Err(new Exception($"Error saving objects: {ex.Message}", ex));
                        }
                    }
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }

        private MySqlConnection GetConnection()
        {
            // Replace with your actual connection string logic
            return
                new MySqlConnection(_connectionString); // Replace with MySql.Data.MySqlClient.MySqlConnection for MySQL
        }
    }
}